package queued

import "sync/atomic"

type JobResType uint32

const (
	JobSuccess JobResType = iota + 1
	JobFail
	JobRePush
	// JobRePushFront
	// JobRePushBack
)

/*
WaitingQueuedJob 排队队列任务接口
*/
type WaitingQueuedJob interface {
	GetJobID() uint64
	RunJob() JobResType
	Abort() bool
	IsDoing() bool
}

type (
	QueueJob func(abort bool) JobResType
)

type CallWaitingQueuedJob struct {
	id          uint64
	job         QueueJob
	doing       atomic.Bool   // 是否正在执行
	failCounter atomic.Uint32 // 重试次数
	maxRetry    uint32        // 最大重试次数
}

func (c *CallWaitingQueuedJob) RunJob() JobResType {
	c.doing.Store(true)
	defer c.doing.Store(false)

	res := c.job(c.Abort())
	if res == JobFail {
		c.failCounter.Add(1)
	}
	return res
}

func (c *CallWaitingQueuedJob) Abort() bool {
	return c.failCounter.Load() >= c.maxRetry
}

func (c *CallWaitingQueuedJob) IsDoing() bool {
	return c.doing.Load()
}

func (c *CallWaitingQueuedJob) GetJobID() uint64 {
	return c.id
}

func NeWWaitingQueuedJob(id uint64, maxRetry uint32, do QueueJob) WaitingQueuedJob {
	return &CallWaitingQueuedJob{
		id:          id,
		job:         do,
		doing:       atomic.Bool{},
		failCounter: atomic.Uint32{},
		maxRetry:    maxRetry,
	}
}
